using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Web;

namespace KJFramework.Helpers
{
	/// <summary>
	///   a helper class for supporting currently Mono Runtime
	///   <para>Higher .NET version: v4.5</para>
	///   <para>Higher Mono version: v3.2</para>
	/// </summary>
	public static class MonoRuntimeHelper
	{
		#region Constructor.
		
		static MonoRuntimeHelper()
		{
			CurrentWorkRoot = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);
		}

		#endregion


		#region Members.

		/// <summary>
		/// 	Get or Set a value which it used to check the currently run mode.
		/// </summary>
		public static bool IsDebugMode{ get; set;}
		/// <summary>
		/// 	Get or Set a Debug config file path.
		/// </summary>
		public static string DebugConfigFilePath{ get; set;}
		/// <summary>
		/// 	Get or Set currently work root.
		/// </summary>
		/// <value>The current work root.</value>
		public static string CurrentWorkRoot{ get; set;}

	    private static Configuration _config;

		#endregion

		#region Methods.

		/// <summary>
		///   Gets currently executable module file name which is the main module except mono.exe/mono-service.exe and so on.
		/// </summary>
		/// <returns>The current execuable file name.</returns>
		public static string GetCurrentExecuableFileName()
		{
			string filename;
			foreach (ProcessModule module in Process.GetCurrentProcess().Modules) 
			{
				filename = Path.GetFileName (module.FileName);
				if(Path.GetExtension(module.FileName) == ".exe")
				{
					if (filename.Contains("mono")) continue;
					return module.FileName;
				}
			}
			return null;
		}

        /// <summary>
        ///   Gets currently executable module file path.
        /// </summary>
        /// <returns>The current execuable file path.</returns>
        public static string GetCurrentExecuableFilePath()
        {
            if (Environment.OSVersion.Platform != PlatformID.Unix) return Directory.GetCurrentDirectory();
            string moduleFile = GetCurrentExecuableFileName();
            return moduleFile == null ? null : Path.GetDirectoryName(moduleFile);
        }

		/// <summary>
		/// 	Calculate currently process's config file path
		/// </summary>
		/// <returns>The current config file path.</returns>
		public static string GetCurrentConfigFilePath()
		{
			if (IsDebugMode) return DebugConfigFilePath;
            if (Environment.OSVersion.Platform != PlatformID.Unix) return SearchConfigFileOnWin32();
			return GetCurrentExecuableFileName() + ".config";
		}

        /// <summary>
        ///     This method will searchs currently useable configuration file path.
        /// </summary>
        /// <returns>return a path of currently process configuration file.</returns>
        private static string SearchConfigFileOnWin32()
        {
			string workDir = HttpContext.Current != null ? HttpContext.Current.Server.MapPath ("~") : MonoRuntimeHelper.CurrentWorkRoot;
			Console.WriteLine ("#Currently work root: " + workDir);
			foreach (string configFile in Directory.GetFiles(workDir, (HttpContext.Current != null ? "*.config" : "*.exe.config"))) return configFile;
            return string.Empty;
        }

        /// <summary>
        ///     Gets currently assembled configuration object.
        /// </summary>
        /// <returns>return assembled configuration object.</returns>
        public static Configuration GetCurrentAssembledConfiguration()
        {
            if (_config == null)
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap { ExeConfigFilename = GetCurrentConfigFilePath() };
                _config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            }
            return _config;
        }

		#endregion
	}
}

